#include "ZhicheEntity.h"
#include "GLTFParser.h"
#include "core/CUtil.h"
#include "Cache.h"

ZhicheEntity::ZhicheEntity(): ModelEntity(ModelType::Zhiche, INT_MAX) {
	loadAsyncDoors();
}

void ZhicheEntity::update() {
	const auto& arg = Cache::zhicheArg();
	setPosition(arg.pos, Config::Y_Model);
	setRotation(arg.angle);
}

void ZhicheEntity::handleDoor(HDir side, Switch status) {//bool isLeft, bool open
	if (!m_isDoorsLoadedDone)// doors not loaded yet, do nothing
		return;

	auto& lastStatus = m_doorStatusMap.valueRef(side);
	if (lastStatus == status)// no change, do nothing
		return;
	lastStatus = status;

	bool left = side == HDir::Left;
	bool open = status == Switch::On;
	const auto& doorModels = left ? m_doorLeftModels : m_doorRightModels;
	const auto& doorMinZPoint = left ? m_doorLeftMinZPoint : m_doorRightMinZPoint;
	auto rotY = (left ? 1 : -1) * (open ? -C_PI/2 : 0);
	const CColor color = "LightCoral";
	for (int i = 0; i < doorModels.size(); i++) {
		auto door = doorModels[i];
		door->setLightEnabled(!open);// or reverse normal vector maybe
		const auto& meshIndexNamePair = door->meshProperty();
		if (meshIndexNamePair.value != "Mirror")
			door->setCullingFaceEnabled(!open);
		door->rotateAround(doorMinZPoint, rotY);
		if (open)
			door->setMaterialColor(color.lighter(100 + i * 6));
		else
			door->setMaterialColor(GLTFParser::material(ModelType::Zhiche, meshIndexNamePair.key).baseColor);// reset to default glTF color
	}
}

void ZhicheEntity::loadAsyncDoors() {
	CUtil::doInBgThread([&] {
		m_doorLeftMinZPoint.z = m_doorRightMinZPoint.z = std::numeric_limits<float>::max();

		const auto& children = ModelEntity::children();
		for (const auto& child : children) {
			const auto& meshIndexName = child->meshProperty();
			int meshIndex = meshIndexName.key;
			const auto& meshName = meshIndexName.value;
			if (meshName.contains("HB_Door_Left")) {// all left door parts
				m_doorLeftModels << child;
				if (meshName.contains("HB_Door_Left_Core")) {// left door main part
					auto& vertices = GLTFParser::vertices(ModelType::Zhiche, meshIndex);
					for (auto& vertex : vertices) {
						if (vertex.z < m_doorLeftMinZPoint.z)
							m_doorLeftMinZPoint = vertex;
					}
				}
			} else if (meshName.contains("HB_Door_Right")) {// all right door parts
				m_doorRightModels << child;
				if (meshName.contains("HB_Door_Right_Core")) {// right door main part
					auto& vertices = GLTFParser::vertices(ModelType::Zhiche, meshIndex);
					for (auto& vertex : vertices) {
						if (vertex.z < m_doorRightMinZPoint.z)
							m_doorRightMinZPoint = vertex;
					}
				}
			}
			if (meshName.contains("Mirror"))// some special parts: mirrors, should be treated standalone/specially, otherwise, bad visual artifacts
				child->setCullingFaceEnabled(false);
		}

		m_doorStatusMap.insert(HDir::Left, Switch::Off);
		m_doorStatusMap.insert(HDir::Right, Switch::Off);

		m_isDoorsLoadedDone = true;
	});
}